// ==UserScript==
// @name         词云
// @namespace    http://tampermonkey.net/
// @version      2024-11-03
// @description  try to take over the world!
// @author       You
// @match        https://www.bilibili.com/video/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=bilibili.com
// @grant        GM_xmlhttpRequest
// @grant        GM_setValue
// @grant        GM_getValue
// @grant        GM.setValue
// @grant        GM.getValue
// @grant        GM_registerMenuCommand
// @run-at document-start
// ==/UserScript==

/* 补环境参数 */
// var t = 'mode=3&oid=113402018078283&pagination_str=%7B%22offset%22%3A%22%7B%5C%22type%5C%22%3A1%2C%5C%22direction%5C%22%3A1%2C%5C%22session_id%5C%22%3A%5C%221772062350790234%5C%22%2C%5C%22data%5C%22%3A%7B%7D%7D%22%7D&plat=1&type=1&web_location=1315875&wts=1730537058ea1db124af3c7062474693fa704f4ff8';
var r = undefined;
var e ={
    "oid": "113402018078283",
    "type": 1,
    "mode": 3,
    "pagination_str": "{\"offset\":\"{\\\"type\\\":1,\\\"direction\\\":1,\\\"data\\\":{\\\"pn\\\":2}}\"}",
    "plat": 1,
    "web_location": 1315875
};
var ct = "wbi_img_urls";

class CommentManager {
    constructor() {
        this.comments = []; // 存储所有的评论
        this.isEnd = false; // 标记评论是否全部请求完毕
        this.length = 0; // 每次请求的评论数量
    }

    // 添加新的评论集合
    addComments(newComments, isEnd) {
        if (Array.isArray(newComments)) {
            this.comments.push(...newComments);
            this.isEnd = isEnd;
            this.length += newComments.length;
        }
    }

    // 过滤评论，参数为正则表达式
    filterComments(regex) {
        return this.comments.filter(comment => regex.test(comment));
    }

    // 获取所有评论
    getAllComments() {
        return this.comments;
    }

    // 获取评论总数
    getTotalCount() {
        return this.length;
    }

    // 检查是否所有评论都已加载
    isAllLoaded() {
        return this.isEnd;
    }
}
(function () {
    'use strict';

    /* hook 获取评论请求的基本参数 */
    const originalFetch = window.fetch;
    var comment_params;

    // 创建一个 Promise 用于监听 comment_params 赋值完成
    const commentParamsReady = new Promise((resolve) => {
        unsafeWindow.fetch = async (resource, config = {}) => {
            // 确保 headers 是一个对象
            if (!config.headers) {
                config.headers = {};
            }
            // 创建 Request 对象
            const request = new Request(resource, config);
            // 检查是否带有特殊标志,跨域请求限制，尝试使用已有的header（由浏览器最后添加的）
            if (config.headers['user-agent']) {
                // 移除标志，防止污染配置
                delete config.headers['X-Skip-Interceptor'];
                return originalFetch(resource, config);
            }

            if (resource.includes('//api.bilibili.com/x/v2/reply/wbi/main')) {
                // 发起请求
                const response = await originalFetch(resource, config);
                const clonedResponse = response.clone(); // 创建响应的副本
                const text = await clonedResponse.text();
                const data = JSON.parse(text);

                // 解析完成，resolve Promise
                resolve({ firstData: data, commentUrl: resource });
                // 返回原始响应
                return response;
            }

            // 对其他请求使用原生 fetch
            return originalFetch(request);
        };
    });

    commentParamsReady
        .then((params) => {
            var offsetString;
            var ltFucRes;
            console.log('comment_params 已经赋值完成:', params);
            /* 
                是否结束滚动 data.data.cursor.is_end
                请求数量 data.data.replies.length
                下一次请求的参数 data.data.cursor.pagination_reply.next_offset
                全部评论数量 data.data.cursor.all_count
            */
            // oid;type;mode;pagination_str;plat;web_location;w_rid;wts;
            comment_params = getUrlComponent(params['commentUrl'].toString());
            e["oid"] = comment_params["oid"];
            e["web_location"] = comment_params['web_location'];
            // comment_params["sessionId"] = params['firstData'].data.cursor.session_id;
            //生成pagination_str参数
            offsetString = params['firstData'].data.cursor.pagination_reply.next_offset;
            const resultObject = {
                offset: offsetString
            };
            e["pagination_str"] = JSON.stringify(resultObject);
            ltFucRes = lt(e);
            comment_params["w_rid"] = ltFucRes["w_rid"];
            comment_params["wts"] = ltFucRes["wts"];
            comment_params["pagination_str"] = JSON.stringify(resultObject);
            return comment_params;
        })
        // .then(async (params) => {
        //     const finalUrl = getFinalCommentUrl(params);
        //     //用已有的安全headers来标记过滤自己的请求
        //     const response = await fetch(finalUrl, {
        //         headers: {
        //             'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36 Edg/130.0.0.0',
        //             'origin': 'https://www.bilibili.com'
        //         }
        //     });
        //     return await response.json();
        // })
        // .then(data => {
        //     // 处理从fetch获得的数据
        //     console.log(data);
        // })
        // .catch(error => {
        //     console.error('Error:', error);
        // });


    const getUrlComponent = function (targetUrl) {
        // 提取查询字符串部分
        const queryString = targetUrl.split('?')[1];
        // 定义正则表达式来匹配参数
        const regex = /([^&=]+)=([^&]*)/g;
        // 创建一个对象来存储参数
        const params = {};
        let match;
        while ((match = regex.exec(queryString)) !== null) {
            const key = decodeURIComponent(match[1]);
            const value = decodeURIComponent(match[2]);
            params[key] = value;
        }
        return params;
    };

    const getFinalCommentUrl = function (params) {
        // 指定参数的顺序
        const orderKeys = ["oid", "type", "mode", "plat", "web_location", "pagination_str", "w_rid", "wts"];
    
        // 按照指定顺序构建参数列表
        const orderedParams = orderKeys
            .filter(key => params.hasOwnProperty(key))
            .map(key => key === 'pagination_str'
                ? `${key}=${encodeURIComponent(params[key])}`
                : `${key}=${params[key]}`);
    
        // 构建新的URL
        const newUrl = 'https://api.bilibili.com/x/v2/reply/wbi/main?' + orderedParams.join('&');
    
        return newUrl;
    };
})();
/* 补环境 */
const t_stringToBytes = function (e) {
    return n_stringToBytes(unescape(encodeURIComponent(e)))
};
const n_stringToBytes = function (e) {
    for (var t = [], r = 0; r < e.length; r++)
        t.push(255 & e.charCodeAt(r));
    return t
};
const e_bytesToWords = function (e) {
    for (var t = [], r = 0, n = 0; r < e.length; r++,
        n += 8)
        t[n >>> 5] |= e[r] << 24 - n % 32;
    return t
};
const o_ff = function (e, t, r, n, o, i, a) {
    var u = e + (t & r | ~t & n) + (o >>> 0) + a;
    return (u << i | u >>> 32 - i) + t
};
const o_gg = function (e, t, r, n, o, i, a) {
    var u = e + (t & n | r & ~n) + (o >>> 0) + a;
    return (u << i | u >>> 32 - i) + t
};
const o_hh = function (e, t, r, n, o, i, a) {
    var u = e + (t ^ r ^ n) + (o >>> 0) + a;
    return (u << i | u >>> 32 - i) + t
};
const o_ii = function (e, t, r, n, o, i, a) {
    var u = e + (r ^ (t | ~n)) + (o >>> 0) + a;
    return (u << i | u >>> 32 - i) + t
};
const t_rotl = function (e, t) {
    return e << t | e >>> 32 - t
};
const e_endian = function (e) {
    if (e.constructor == Number)
        return 16711935 & t_rotl(e, 8) | 4278255360 & t_rotl(e, 24);
    for (var r = 0; r < e.length; r++)
        e[r] = e_endian(e[r]);
    return e
};
const o = function o(i, a) {
    i.constructor == String ? i = a && "binary" === a.encoding ? n_stringToBytes(i) : t_stringToBytes(i) : r(i) ? i = Array.prototype.slice.call(i, 0) : Array.isArray(i) || i.constructor === Uint8Array || (i = i.toString());
    for (var u = e_bytesToWords(i), s = 8 * i.length, c = 1732584193, l = -271733879, f = -1732584194, d = 271733878, p = 0; p < u.length; p++)
        u[p] = 16711935 & (u[p] << 8 | u[p] >>> 24) | 4278255360 & (u[p] << 24 | u[p] >>> 8);
    u[s >>> 5] |= 128 << s % 32,
        u[14 + (s + 64 >>> 9 << 4)] = s;
    var h = o_ff
        , y = o_gg
        , v = o_hh
        , b = o_ii;
    for (p = 0; p < u.length; p += 16) {
        var m = c
            , w = l
            , g = f
            , x = d;
        c = h(c, l, f, d, u[p + 0], 7, -680876936),
            d = h(d, c, l, f, u[p + 1], 12, -389564586),
            f = h(f, d, c, l, u[p + 2], 17, 606105819),
            l = h(l, f, d, c, u[p + 3], 22, -1044525330),
            c = h(c, l, f, d, u[p + 4], 7, -176418897),
            d = h(d, c, l, f, u[p + 5], 12, 1200080426),
            f = h(f, d, c, l, u[p + 6], 17, -1473231341),
            l = h(l, f, d, c, u[p + 7], 22, -45705983),
            c = h(c, l, f, d, u[p + 8], 7, 1770035416),
            d = h(d, c, l, f, u[p + 9], 12, -1958414417),
            f = h(f, d, c, l, u[p + 10], 17, -42063),
            l = h(l, f, d, c, u[p + 11], 22, -1990404162),
            c = h(c, l, f, d, u[p + 12], 7, 1804603682),
            d = h(d, c, l, f, u[p + 13], 12, -40341101),
            f = h(f, d, c, l, u[p + 14], 17, -1502002290),
            c = y(c, l = h(l, f, d, c, u[p + 15], 22, 1236535329), f, d, u[p + 1], 5, -165796510),
            d = y(d, c, l, f, u[p + 6], 9, -1069501632),
            f = y(f, d, c, l, u[p + 11], 14, 643717713),
            l = y(l, f, d, c, u[p + 0], 20, -373897302),
            c = y(c, l, f, d, u[p + 5], 5, -701558691),
            d = y(d, c, l, f, u[p + 10], 9, 38016083),
            f = y(f, d, c, l, u[p + 15], 14, -660478335),
            l = y(l, f, d, c, u[p + 4], 20, -405537848),
            c = y(c, l, f, d, u[p + 9], 5, 568446438),
            d = y(d, c, l, f, u[p + 14], 9, -1019803690),
            f = y(f, d, c, l, u[p + 3], 14, -187363961),
            l = y(l, f, d, c, u[p + 8], 20, 1163531501),
            c = y(c, l, f, d, u[p + 13], 5, -1444681467),
            d = y(d, c, l, f, u[p + 2], 9, -51403784),
            f = y(f, d, c, l, u[p + 7], 14, 1735328473),
            c = v(c, l = y(l, f, d, c, u[p + 12], 20, -1926607734), f, d, u[p + 5], 4, -378558),
            d = v(d, c, l, f, u[p + 8], 11, -2022574463),
            f = v(f, d, c, l, u[p + 11], 16, 1839030562),
            l = v(l, f, d, c, u[p + 14], 23, -35309556),
            c = v(c, l, f, d, u[p + 1], 4, -1530992060),
            d = v(d, c, l, f, u[p + 4], 11, 1272893353),
            f = v(f, d, c, l, u[p + 7], 16, -155497632),
            l = v(l, f, d, c, u[p + 10], 23, -1094730640),
            c = v(c, l, f, d, u[p + 13], 4, 681279174),
            d = v(d, c, l, f, u[p + 0], 11, -358537222),
            f = v(f, d, c, l, u[p + 3], 16, -722521979),
            l = v(l, f, d, c, u[p + 6], 23, 76029189),
            c = v(c, l, f, d, u[p + 9], 4, -640364487),
            d = v(d, c, l, f, u[p + 12], 11, -421815835),
            f = v(f, d, c, l, u[p + 15], 16, 530742520),
            c = b(c, l = v(l, f, d, c, u[p + 2], 23, -995338651), f, d, u[p + 0], 6, -198630844),
            d = b(d, c, l, f, u[p + 7], 10, 1126891415),
            f = b(f, d, c, l, u[p + 14], 15, -1416354905),
            l = b(l, f, d, c, u[p + 5], 21, -57434055),
            c = b(c, l, f, d, u[p + 12], 6, 1700485571),
            d = b(d, c, l, f, u[p + 3], 10, -1894986606),
            f = b(f, d, c, l, u[p + 10], 15, -1051523),
            l = b(l, f, d, c, u[p + 1], 21, -2054922799),
            c = b(c, l, f, d, u[p + 8], 6, 1873313359),
            d = b(d, c, l, f, u[p + 15], 10, -30611744),
            f = b(f, d, c, l, u[p + 6], 15, -1560198380),
            l = b(l, f, d, c, u[p + 13], 21, 1309151649),
            c = b(c, l, f, d, u[p + 4], 6, -145523070),
            d = b(d, c, l, f, u[p + 11], 10, -1120210379),
            f = b(f, d, c, l, u[p + 2], 15, 718787259),
            l = b(l, f, d, c, u[p + 9], 21, -343485551),
            c = c + m >>> 0,
            l = l + w >>> 0,
            f = f + g >>> 0,
            d = d + x >>> 0
    }
    return e_endian([c, l, f, d])
};
function ft(e) {
    return e.substring(e.lastIndexOf("/") + 1, e.length).split(".")[0]
};
const e_wordsToBytes = function (e) {
    for (var t = [], r = 0; r < 32 * e.length; r += 8)
        t.push(e[r >>> 5] >>> 24 - r % 32 & 255);
    return t
};
const e_bytesToHex = function (e) {
    for (var t = [], r = 0; r < e.length; r++)
        t.push((e[r] >>> 4).toString(16)),
            t.push((15 & e[r]).toString(16));
    return t.join("")
};
const at = function (t, r) {
    if (null == t)
        throw new Error("Illegal argument " + t);
    var i = e_wordsToBytes(o(t, r));
    return r && r.asBytes ? i : r && r.asString ? n.bytesToString(i) : e_bytesToHex(i)
};
function lt(e) {
    var t, r, n = function (e) {
        var t;
        if (e.useAssignKey)
            return {
                imgKey: e.wbiImgKey,
                subKey: e.wbiSubKey
            };
        var r = (null === (t = function (e) {
            try {
                return localStorage.getItem(e)
            } catch (e) {
                return null
            }
        }(ct)) || void 0 === t ? void 0 : t.split("-")) || []
            , n = r[0]
            , o = r[1]
            , i = n ? ft(n) : e.wbiImgKey
            , a = o ? ft(o) : e.wbiSubKey;
        return {
            imgKey: i,
            subKey: a
        }
    }(arguments.length > 1 && void 0 !== arguments[1] ? arguments[1] : {
        wbiImgKey: "",
        wbiSubKey: ""
    }), o = n.imgKey, i = n.subKey;
    if (o && i) {
        for (var a = (t = o + i,
            r = [],
            [46, 47, 18, 2, 53, 8, 23, 32, 15, 50, 10, 31, 58, 3, 45, 35, 27, 43, 5, 49, 33, 9, 42, 19, 29, 28, 14, 39, 12, 38, 41, 13, 37, 48, 7, 16, 24, 55, 40, 61, 26, 17, 0, 1, 60, 51, 30, 4, 22, 25, 54, 21, 56, 59, 6, 63, 57, 62, 11, 36, 20, 34, 44, 52].forEach((function (e) {
                t.charAt(e) && r.push(t.charAt(e))
            }
            )),
            r.join("").slice(0, 32)), u = Math.round(Date.now() / 1e3), s = Object.assign({}, e, {
                wts: u
            }), c = Object.keys(s).sort(), l = [], f = /[!'()*]/g, d = 0; d < c.length; d++) {
            var p = c[d]
                , h = s[p];
            h && "string" == typeof h && (h = h.replace(f, "")),
                null != h && l.push("".concat(encodeURIComponent(p), "=").concat(encodeURIComponent(h)))
        }
        var y = l.join("&");
        return {
            w_rid: at(y + a),
            wts: u.toString()
        }
    }
    return null
};